{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Working on a Windows 10\n", "Python version 3.11.8 | packaged by conda-forge | (main, Feb 16 2024, 20:40:50) [MSC v.1937 64 bit (AMD64)]\n", "Pandas version 2.2.3\n", "bifacial_radiance version 0.5.0b2.dev4+gedb973d.d20250924\n" ] } ], "source": [ "# This information helps with debugging and getting support :)\n", "import sys, platform\n", "import pandas as pd\n", "import bifacial_radiance as br\n", "print(\"Working on a \", platform.system(), platform.release())\n", "print(\"Python version \", sys.version)\n", "print(\"Pandas version \", pd.__version__)\n", "print(\"bifacial_radiance version \", br.__version__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 4 - Debugging with Custom Objects\n", "## Fixed Tilt 2-up with Torque Tube + CLEAN Routine + CustomObject\n", "\n", "This journal has examples of various things, some which hav ebeen covered before and some in more depth:\n", "\n", "* Running a fixed_tilt simulation beginning to end.\n", "* Creating a 2-up module with torque-tube, and detailed geometry of spacings in xgap, ygap and zgap.\n", "* Calculating the tracker angle for a specific time, in case you want to use that value to model a fixed_tilt setup.\n", "* Loading and cleaning results, particularly important when using setups with torquetubes / ygaps. \n", "* Adding a \"Custom Object\" or **marker** at the Origin of the Scene, to do a visual sanity-check of the geometry. \n", "\n", "It will look something like this (without the marker in this visualization):\n", "\n", "![What we are trying to re-create](../images_wiki/Journal_example_torquetube.PNG)\n", "\n", "***STEPS:***\n", "\n", "1. Specify Working Folder and Import Program \n", "2. Specify all variables \n", "3. Create the Radiance Object and generate the Sky \n", "4. Calculating tracker angle/geometry for a specific timestamp \n", "5. Making the Module & the Scene, Visualize and run Analysis \n", "6. Calculate Bifacial Ratio (clean results) \n", "7. Add Custom Elements to your Scene Example: Marker at 0,0 position " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Specify Working Folder and Import Program\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Your simulation will be stored in C:\\Users\\cdeline\\Documents\\Python Scripts\\Bifacial_Radiance\\bifacial_radiance\\TEMP\\Tutorial_04\n" ] } ], "source": [ "import os\n", "from pathlib import Path\n", "\n", "testfolder = Path().resolve().parent.parent / 'bifacial_radiance' / 'TEMP' / 'Tutorial_04'\n", "\n", "# Another option using relative address; for some operative systems you might need '/' instead of '\\'\n", "# testfolder = os.path.abspath(r'..\\..\\bifacial_radiance\\TEMP') \n", "\n", "print (\"Your simulation will be stored in %s\" % testfolder)\n", "\n", "if not os.path.exists(testfolder):\n", " os.makedirs(testfolder)\n", "\n", "import bifacial_radiance\n", "import numpy as np\n", "import pandas as pd" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Specify all variables for the module and scene\n", "\n", "Below find a list of all of the possible parameters for makeModule. \n", "scene and simulation parameters are also organized below. \n", "This simulation will be a complete simulation in terms of parameters that you can modify.\n", "\n", "The below routine creates a HEXAGONAL torque tube, for a 2-UP configuration of a specific module size. Parameters for the module, the torque tube, and the scene are below.\n", "This is being run with gendaylit, for one specific timestamp" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "simulationname = 'tutorial_4'\n", "\n", "## SceneDict Parameters\n", "gcr = 0.33 # ground cover ratio, = module_height / pitch\n", "albedo = 0.28 #'concrete' # ground albedo\n", "hub_height = 2.35 # we could also pass clearance_height. \n", "azimuth_ang = 90 # Modules will be facing East.\n", "lat = 37.5\n", "lon = -77.6\n", "nMods = 4 # doing a smaller array for better visualization on this example.\n", "nRows = 2 \n", "\n", "# MakeModule Parameters\n", "module_type='test-module'\n", "x = 1.996 # landscape, sinze x > y. Remember that orientation has been deprecated.\n", "y = 0.991\n", "tilt = 10\n", "numpanels = 2 # doing a 2-up system!\n", "\n", "\n", "# Gaps:\n", "xgap = 0.05 # distance between modules in the row.\n", "ygap = 0.15 # distance between the 2 modules along the collector slope.\n", "zgap = 0.175 # if there is a torquetube, this is the distance between the torquetube and the modules.\n", "# If there is not a module, zgap is the distance between the module and the axis of rotation (relevant for \n", "# tracking systems. \n", "\n", "# TorqueTube Parameters\n", "tubetype = 'Hex'\n", "diameter = 0.15\n", "material = 'Metal_Grey' # IT's NOT GRAY, IT's GREY.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Create the Radiance Object and generate the Sky" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "path = C:\\Users\\cdeline\\Documents\\Python Scripts\\Bifacial_Radiance\\bifacial_radiance\\TEMP\\Tutorial_04\n", "Making path: images\n", "Making path: objects\n", "Making path: results\n", "Making path: skies\n", "Making path: EPWs\n", "Making path: materials\n", "Loading albedo, 1 value(s), 0.280 avg\n", "1 nonzero albedo values.\n", "Getting weather file: USA_VA_Richmond.724010_TMY2.epw\n", " ... OK!\n", "8760 line in WeatherFile. Assuming this is a standard hourly WeatherFile for the year for purposes of saving Gencumulativesky temporary weather files in EPW folder.\n", "Coercing year to 2001\n", "Saving file EPWs\\metdata_temp.csv, # points: 8760\n", "Calculating Sun position for Metdata that is right-labeled with a delta of -30 mins. i.e. 12 is 11:30 sunpos\n" ] }, { "data": { "text/plain": [ "'skies\\\\sky2_37.5_-77.33_2001-06-17_1300.rad'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "demo = bifacial_radiance.RadianceObj(simulationname, path=str(testfolder)) # Create a RadianceObj 'object'\n", "demo.setGround(albedo) # input albedo number or material name like 'concrete'. To see options, run this without any input.\n", "epwfile = demo.getEPW(lat,lon) # pull TMY data for any global lat/lon\n", "metdata = demo.readWeatherFile(epwfile, coerce_year=2001) # read in the EPW weather data from above\n", "\n", "timestamp = metdata.datetime.index(pd.to_datetime('2001-06-17 13:0:0 -5')) # Make this timezone aware, use -5 for EST.\n", "demo.gendaylit(timestamp) # Mid-day, June 17th" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Calculating tracker angle/geometry for a specific timestamp\n", "\n", "This trick is useful if you are trying to use the fixed-tilt steps in bifacial_radiance to model a tracker for one specific point in time (if you take a picture of a tracker, it looks fixed, right? Well then). \n", "\n", "We assigned a 10 degree tilt at the beginning, but if we were to model a tracker as a fixed-tilt element because we are interested in only one point in time, this routine will tell us what tilt to use. *Please note that to model a tracker as fixed tilt, we suggest passing a hub_height, otherwise you will have to calculate the clearance_height manually.*\n", "\n", "
\n", "Details: you might have noticed in the previoust tutorial looking at the tracker dictionary, but the way that bifacial_radiance handles tracking: If the tracker is N-S axis azimuth, the surface azimuth of the modules will be set to 90 always, with a tilt that is either positive (for the early morning, facing East), or negative (for the afternoon, facing west).\n", "
\n" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " NEW Calculated Tilt: -4.67 \n" ] } ], "source": [ "# Some tracking parameters that won't be needed after getting this angle:\n", "axis_azimuth = 180\n", "axis_tilt = 0\n", "limit_angle = 60\n", "backtrack = True\n", "tilt = demo.getSingleTimestampTrackerAngle(timeindex=timestamp, gcr=gcr, azimuth=axis_azimuth, axis_tilt=axis_tilt, limit_angle=limit_angle, backtrack=backtrack)\n", "\n", "print (\"\\n NEW Calculated Tilt: %s \" % tilt)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Making the Module & the Scene, Visualize and run Analysis" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Module Name: test-module\n", "Module test-module updated in module.json\n", "Module test-module updated in module.json\n", "Pre-existing .rad file objects\\test-module.rad will be overwritten\n", "\n", "Created tutorial_4.oct\n" ] } ], "source": [ "# Making module with all the variables\n", "module = demo.makeModule(name=module_type,x=x,y=y,bifi=1, \n", " zgap=zgap, ygap=ygap, xgap=xgap, numpanels=numpanels)\n", "module.addTorquetube(diameter=diameter, material=material, tubetype=tubetype,\n", " visible=True, axisofrotation=True)\n", "\n", "# create a scene with all the variables. \n", "# Specifying the pitch automatically with the collector width (sceney) returned by the module object.\n", "# Height has been deprecated as an input. pass clearance_height or hub_height in the scenedict.\n", "\n", "sceneDict = {'tilt':tilt,'pitch': np.round(module.sceney / gcr,3),\n", " 'hub_height':hub_height,'azimuth':azimuth_ang, \n", " 'module_type':module_type, 'nMods': nMods, 'nRows': nRows} \n", "\n", "scene = demo.makeScene(module=module, sceneDict=sceneDict) #makeScene creates a .rad file of the Scene\n", "\n", "octfile = demo.makeOct(demo.getfilelist()) # makeOct combines all of the ground, sky and object files into a .oct file." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At this point you should be able to go into a command window (cmd.exe) and check the geometry. It should look like the image at the beginning of the journal. Example:\n", " \n", "***rvu -vf views\\front.vp -e .01 -pe 0.02 -vp -2 -12 14.5 tutorial_4.oct****\n" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "\n", "## Comment the line below to run rvu from the Jupyter notebook instead of your terminal.\n", "## Simulation will stop until you close the rvu window\n", "\n", "#!rvu -vf views\\front.vp -e .01 tutorial_4.oct\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And then proceed happily with your analysis:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Linescan in process: tutorial_4_Row1_Module2_Front\n", "Linescan in process: tutorial_4_Row1_Module2_Back\n", "Saved: results\\irr_tutorial_4_Row1_Module2.csv\n" ] } ], "source": [ "analysis = bifacial_radiance.AnalysisObj(octfile, demo.name) # return an analysis object including the scan dimensions for back irradiance\n", "\n", "sensorsy = 200 # setting this very high to see a detailed profile of the irradiance, including\n", "#the shadow of the torque tube on the rear side of the module.\n", "frontscan, backscan = analysis.moduleAnalysis(scene, modWanted = 2, rowWanted = 1, sensorsy = 200)\n", "frontDict, backDict = analysis.analysis(octfile, demo.name, frontscan, backscan) # compare the back vs front irradiance \n", "\n", "# print('\"Annual\" bifacial ratio average: %0.3f' %( sum(analysis.Wm2Back) / sum(analysis.Wm2Front) ) )\n", "# See comment below of why this line is commented out." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## 6. Calculate Bifacial Ratio (clean results)\n", "\n", "Although we could calculate a bifacial ratio average at this point, this value would be misleading, since some of the sensors generated will fall on the torque tube, the sky, and/or the ground since we have torquetube and ygap in the scene. To calculate the real bifacial ratio average, we must use the clean routines.\n" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Printing the dataframe containing the results just calculated in results/irr_tutorial_4_Row1_Module2.csv: \n" ] }, { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
xyzrearZmattyperearMatWm2FrontWm2BackBack/FrontRatiorearXrearY
01.0290.02.7102.680a1.0.a0.test-module.6457a1.0.a0.test-module.2310909.867186.2610.2051.0320.0
11.0190.02.7102.680a1.0.a0.test-module.6457a1.0.a0.test-module.2310909.868186.0470.2041.0210.0
21.0080.02.7092.678a1.0.a0.test-module.6457a1.0.a0.test-module.2310909.868185.8490.2041.0110.0
30.9980.02.7092.678a1.0.a0.test-module.6457a1.0.a0.test-module.2310909.868185.6350.2041.0000.0
40.9870.02.7072.676a1.0.a0.test-module.6457a1.0.a0.test-module.2310909.868185.4310.2040.9900.0
....................................
195-1.0330.02.5432.512a1.0.a1.test-module.6457a1.0.a1.test-module.2310909.878185.5600.204-1.0300.0
196-1.0430.02.5412.510a1.0.a1.test-module.6457a1.0.a1.test-module.2310909.878185.7430.204-1.0400.0
197-1.0550.02.5412.510a1.0.a1.test-module.6457a1.0.a1.test-module.2310909.878185.9580.204-1.0520.0
198-1.0640.02.5402.508a1.0.a1.test-module.6457a1.0.a1.test-module.2310909.878186.1410.205-1.0620.0
199-1.0740.02.5402.508a1.0.a1.test-module.6457a1.0.a1.test-module.2310909.878186.1440.205-1.0710.0
\n", "

200 rows × 11 columns

\n", "
" ], "text/plain": [ " x y z rearZ mattype \\\n", "0 1.029 0.0 2.710 2.680 a1.0.a0.test-module.6457 \n", "1 1.019 0.0 2.710 2.680 a1.0.a0.test-module.6457 \n", "2 1.008 0.0 2.709 2.678 a1.0.a0.test-module.6457 \n", "3 0.998 0.0 2.709 2.678 a1.0.a0.test-module.6457 \n", "4 0.987 0.0 2.707 2.676 a1.0.a0.test-module.6457 \n", ".. ... ... ... ... ... \n", "195 -1.033 0.0 2.543 2.512 a1.0.a1.test-module.6457 \n", "196 -1.043 0.0 2.541 2.510 a1.0.a1.test-module.6457 \n", "197 -1.055 0.0 2.541 2.510 a1.0.a1.test-module.6457 \n", "198 -1.064 0.0 2.540 2.508 a1.0.a1.test-module.6457 \n", "199 -1.074 0.0 2.540 2.508 a1.0.a1.test-module.6457 \n", "\n", " rearMat Wm2Front Wm2Back Back/FrontRatio rearX \\\n", "0 a1.0.a0.test-module.2310 909.867 186.261 0.205 1.032 \n", "1 a1.0.a0.test-module.2310 909.868 186.047 0.204 1.021 \n", "2 a1.0.a0.test-module.2310 909.868 185.849 0.204 1.011 \n", "3 a1.0.a0.test-module.2310 909.868 185.635 0.204 1.000 \n", "4 a1.0.a0.test-module.2310 909.868 185.431 0.204 0.990 \n", ".. ... ... ... ... ... \n", "195 a1.0.a1.test-module.2310 909.878 185.560 0.204 -1.030 \n", "196 a1.0.a1.test-module.2310 909.878 185.743 0.204 -1.040 \n", "197 a1.0.a1.test-module.2310 909.878 185.958 0.204 -1.052 \n", "198 a1.0.a1.test-module.2310 909.878 186.141 0.205 -1.062 \n", "199 a1.0.a1.test-module.2310 909.878 186.144 0.205 -1.071 \n", "\n", " rearY \n", "0 0.0 \n", "1 0.0 \n", "2 0.0 \n", "3 0.0 \n", "4 0.0 \n", ".. ... \n", "195 0.0 \n", "196 0.0 \n", "197 0.0 \n", "198 0.0 \n", "199 0.0 \n", "\n", "[200 rows x 11 columns]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "resultFile='results/irr_tutorial_4_Row1_Module2.csv'\n", "results_loaded = bifacial_radiance.load.read1Result(resultFile)\n", "print(\"Printing the dataframe containing the results just calculated in %s: \" % resultFile)\n", "results_loaded" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Looking at only 1 sensor in the middle -- position 100 out of the 200 sensors sampled:\n" ] }, { "data": { "text/plain": [ "x -0.028\n", "y 0.0\n", "z 2.625\n", "rearZ 2.594\n", "mattype a1.0.hextube1a.6457\n", "rearMat sky\n", "Wm2Front 814.726\n", "Wm2Back 161.885\n", "Back/FrontRatio 0.199\n", "rearX -0.025\n", "rearY 0.0\n", "Name: 100, dtype: object" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"Looking at only 1 sensor in the middle -- position 100 out of the 200 sensors sampled:\")\n", "results_loaded.loc[100]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "As an example, we can see above that sensor 100 falls in the hextube, and in the sky. We need to remove this to calculate the real bifacial_gain from the irradiance falling into the modules. To do this we use cleanResult form the load.py module in bifacial_radiance. This finds the invalid materials and sets the irradiance values for those materials to NaN\n", "\n", "This might take some time in the current version. " ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "# Cleaning Results:\n", "# remove invalid materials and sets the irradiance values to NaN\n", "clean_results = bifacial_radiance.load.cleanResult(results_loaded) " ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Sampling the same location as before to see what the results are now:\n" ] }, { "data": { "text/plain": [ "x -0.028\n", "y 0.0\n", "z 2.625\n", "rearZ 2.594\n", "mattype a1.0.hextube1a.6457\n", "rearMat sky\n", "Wm2Front NaN\n", "Wm2Back NaN\n", "Back/FrontRatio 0.199\n", "rearX -0.025\n", "rearY 0.0\n", "Name: 100, dtype: object" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"Sampling the same location as before to see what the results are now:\")\n", "clean_results.loc[100]" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CORRECT Annual bifacial ratio average: 0.200\n", "\n", "(If we had not done the cleaning routine, the bifacial ratio would have been calculated to 0.202 <-- THIS VALUE IS WRONG)\n" ] } ], "source": [ "print('CORRECT Annual bifacial ratio average: %0.3f' %( clean_results['Wm2Back'].sum() / clean_results['Wm2Front'].sum() ))\n", "\n", "print (\"\\n(If we had not done the cleaning routine, the bifacial ratio would have been \", \\\n", " \"calculated to %0.3f <-- THIS VALUE IS WRONG)\" %( sum(analysis.Wm2Back) / sum(analysis.Wm2Front) )) \n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Add Custom Elements to your Scene Example: Marker at 0,0 position\n", "This shows how to add a custom element, in this case a Cube, that will be placed in the center of your already created scene to mark the 0,0 location. \n", "\n", "This can be added at any point after makeScene has been run once. Notice that if this extra element is in the scene and the analysis sensors fall on this element, they will measure irradiance at this element and no the modules. **New in v0.5.0**: Multiple sceneobjects can be added to the scene, using `customtext` parameter and `append=True`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are going to create a \"MyMarker.rad\" file in the objects folder, right after we make the Module. \n", "This is a prism (so we use 'genbox'), that is black from the ground.rad list of materials ('black')\n", "We are naming it 'CenterMarker'\n", "Its sides are going to be 0.5x0.5x0.5 m \n", "and We are going to leave its bottom surface coincident with the plane z=0, but going to center on X and Y." ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Custom Object Name objects\\MyMarker.rad\n" ] } ], "source": [ "name='MyMarker'\n", "text='! genbox black CenterMarker 0.1 0.1 4 | xform -t -0.05 -0.05 0'\n", "customObject = demo.makeCustomObject(name,text)\n", "\n", " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This should have created a MyMarker.rad object on your objects folder.\n", "\n", "But creating the object does not automatically adds it to the scene. So let's now add the customObject to the Scene. We are not going to translate it or anything because we want it at the center, but you can pass translation, rotation, and any other XFORM command from Radiance. The custom object is added to the scene .rad file.\n", "\n", "Starting in v0.5.0 we can have multiple scenes, and these are now stored in the array `demo.scenes`.\n" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ " : {'gcr': np.float64(0.32998), 'hpc': False, 'module': : {'x': 1.996, 'y': 0.991, 'z': 0.02, 'modulematerial': 'black', 'scenex': np.float64(2.046), 'sceney': np.float64(2.132), 'scenez': np.float64(0.25), 'numpanels': 2, 'bifi': 1, 'text': '! genbox black test-module 1.996 0.991 0.02 | xform -t -0.998 -1.066 0.25 -a 2 -t 0 1.141 0\\r\\n! genbox Metal_Grey hextube1a 2.046 0.075 0.129904 | xform -t -1.023 -0.0375 -0.064952\\r\\n! genbox Metal_Grey hextube1b 2.046 0.075 0.129904 | xform -t -1.023 -0.0375 0.064952 -rx 60 -t 0 0 0\\r\\n! genbox Metal_Grey hextube1c 2.046 0.075 0.129904 | xform -t -1.023 -0.0375 -0.064952 -rx -60 -t 0 0 0', 'modulefile': 'objects\\\\test-module.rad', 'glass': False, 'glassEdge': 0.01, 'offsetfromaxis': np.float64(0.25), 'xgap': 0.05, 'ygap': 0.15, 'zgap': 0.175}, 'modulefile': 'objects\\\\test-module.rad', 'name': 'Scene0', 'radfiles': ['objects\\\\test-module_C_2.28_rtr_6.46_tilt_-5_4modsx2rows_origin0,0.rad'], 'sceneDict': {'tilt': -4.67, 'pitch': np.float64(6.461), 'hub_height': 2.35, 'azimuth': 90, 'module_type': 'test-module', 'nMods': 4, 'nRows': 2, 'axis_tilt': 0, 'originx': 0, 'originy': 0}, 'text': '!xform -rx -4.67 -t 0 0 2.35 -a 4 -t 2.046 0 0 -a 2 -t 0 6.461 0 -i 1 -t -2.046 -0.0 0 -rz 90 -t 0 0 0 \"objects\\\\test-module.rad\"'}" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "demo.scenes[0]" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['objects\\\\test-module_C_2.28_rtr_6.46_tilt_-5_4modsx2rows_origin0,0.rad']" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "demo.scenes[0].radfiles" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [], "source": [ "# Append the custom object. It should now show up in the scene radfile.\n", "scene = demo.scenes[0].appendtoScene(customObject=customObject)\n" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Created tutorial_4.oct\n" ] } ], "source": [ "# makeOct combines all of the ground, sky and object files into a .oct file.\n", "octfile = demo.makeOct(demo.getfilelist()) " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "appendtoScene appended to the Scene.rad file the name of the custom object we created and the xform transformation we included as text. Then octfile merged this new scene with the ground and sky files.\n", "\n", "At this point you should be able to go into a command window (cmd.exe) and check the geometry, and the marker should be there. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "## Comment the line below to run rvu from the Jupyter notebook instead of your terminal.\n", "## Simulation will stop until you close the rvu window\n", "\n", "#!rvu -vf views\\front.vp -e .01 tutorial_4.oct\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you ran the getTrackerAngle detour and appended the marker, it should look like this:\n", "\n", "\n", "![Marker position at 0,0](../images_wiki/Journal_example_marker_origin.PNG)\n", "\n", "If you do an analysis and any of the sensors hits the Box object we just created, the list of materials in the result.csv file should say something with \"CenterMarker\" on it. \n", "\n", "***See more examples of the use of makeCustomObject and appendtoScene on the Bifacial Carport/Canopies Tutorial*** " ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.13" } }, "nbformat": 4, "nbformat_minor": 2 }